/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *  * * * * * * * * * * *
 *            Copyright (C) 2018 Institute of Computing Technology, CAS
 *               Author : Han Shukai (email : hanshukai@ict.ac.cn)
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *  * * * * * * * * * * *
 *                  The shell acts as a task running in user mode.
 *       The main function is to make system calls through the user's output.
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *  * * * * * * * * * * *
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this
 * software and associated documentation files (the "Software"), to deal in the Software
 * without restriction, including without limitation the rights to use, copy, modify,
 * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
 * persons to whom the Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *  * * * * * * * * * * */

#include <test.h>
#include <string.h>
#include <sys/syscall.h>
#include <stdio.h>
#include <stdint.h>

struct task_info task_test_waitpid = {
    (uintptr_t)&wait_exit_task, USER_PROCESS, 1};
/*
struct task_info task_test_semaphore = {
    (uintptr_t)&semaphore_add_task1, USER_PROCESS, 1};
*/
struct task_info task_test_condition = {
    (uintptr_t)&test_condition, USER_PROCESS, 1};
struct task_info task_test_barrier = {
    (uintptr_t)&test_barrier, USER_PROCESS, 1};

struct task_info task13 = {(uintptr_t)&SunQuan, USER_PROCESS, 1};
struct task_info task14 = {(uintptr_t)&LiuBei, USER_PROCESS, 1};
struct task_info task15 = {(uintptr_t)&CaoCao, USER_PROCESS, 1};
struct task_info task_test_multicore = {(uintptr_t)&test_multicore, USER_PROCESS, 1};

static struct task_info *test_tasks[16] = {&task_test_waitpid,
                                           NULL,//&task_test_semaphore,
                                           &task_test_condition,
                                           &task_test_barrier,
                                           &task13, &task14, &task15,
                                           &task_test_multicore};
static int num_test_tasks = 8;

#define SHELL_BEGIN 25
int my_atoi(char *s){
  int i=0,n;
  if(s[i]=='+' || s[i] == '-')
    ++i;
  for(n=0; s[i]!='\0';i++){
    n = n*10 + (s[i]-'0');
  }
  return n;
}

void parse_cmd(char argv[][15],int argc){
    if(argc == 1){
        if(!strcmp(argv[0], "ps")){
            sys_process_show();
        }
        else if(!strcmp(argv[0], "clear"))
            sys_screen_clear();
        else
            printf("Unknown command!\r");
    }
    else if(argc == 2){
        int pid = my_atoi((char *)argv[1]);
        if(!strcmp(argv[0], "exec"))
        {
            sys_spawn(test_tasks[pid-1], NULL, AUTO_CLEANUP_ON_EXIT);
            printf("exec process[%d]\n", pid);
        }
        else if(!strcmp(argv[0], "kill"))
        {
            sys_kill(pid);
            printf("kill process pid = %d\n", pid);
        }
        else
            printf("Unknown command!\n");
    }
    else if(argc != 0)
        printf("Unknown command!\r");

}

void test_shell()
{
    char cmd_buffer[100] ;
    char argv[3][15];
    int argc;
    int i = 0;
    int ch;
    int arg_x =0, arg_y =0;
    sys_move_cursor(1, SHELL_BEGIN);
    printf("------------------- COMMAND -------------------\r");
    printf("> root@UCAS_OS: ");

    while (1)
    {
        ch = sys_getchar();
        if(ch != -1){
            //echo
            sys_putchar((char)ch);

            if(ch == '\n' || ch == '\r'){
                cmd_buffer[i] = ch;
                int j = 0;
                if(cmd_buffer[j] == ' '){
                    while(cmd_buffer[j] == ' ' && j <= i)
                        j++;
                    j--;
                }
                if(j<i){
                    argc = 1;
                }

                for(arg_x = 0, arg_y = 0; cmd_buffer[j] != '\r'; j++){
                    if(cmd_buffer[j] == ' '){
                        while(cmd_buffer[j] == ' ' && j <= i)
                            j++;
                        j--;
                        argv[arg_x][arg_y] = '\0';
                        argc ++;
                        arg_x ++;
                        arg_y = 0;
                    }else{
                        argv[arg_x][arg_y] = cmd_buffer[j];
                        arg_y++;
                    }
                }
                // TODO: ps, exec, kill, clear
                parse_cmd(argv, argc);

                i = 0;
                arg_x = 0;
                printf("> root@UCAS_OS: ");

                for(int j =0; j<100; j++)
                    cmd_buffer[j] = '\0';

                for(int j2=0;j2<15;j2++)
                    for(int j1 = 0; j1<3;j1++)
                        argv[j1][j2] = '\0';
            }
            else if(ch != 127 && ch != 8){
            cmd_buffer[i] = ch;
            i++;
            }
            else if(i){
                i--;
                cmd_buffer[i] = '\0';
            }
        }
    } 
}    
